package com.kylin.core.order.event.repository;

import com.kylin.core.order.query.handler.OrderTranslator;
import com.kylin.dal.entity.order.*;
import com.kylin.domain.order.vo.OrderAddressVO;
import com.kylin.domain.order.vo.OrderLineVO;
import com.kylin.domain.order.vo.OrderMainVO;
import com.kylin.domain.order.vo.OrderRefundVO;
import com.kylin.shared.common.consts.Constants;
import com.kylin.shared.enums.RefundState;
import com.kylin.shared.id.impl.TimestampIdFactory;
import com.kylin.shared.utils.MappingTools;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import javax.persistence.EntityManager;

/**
 * 操作订单表的数据查询功能
 * @author Damon S.
 * @version v1.0.1
 * @date 2019年11月10日 14:55
 */
@Slf4j
@Component
public final class OrderDataHandler {

    private final JPAQueryFactory orderQueryFactory;

    private final QOrderMainEntry qOrderMainEntry;
    private final QOrderAddressEntry qOrderAddressEntry;
    private final QOrderLineItemEntry qOrderLineItemEntry;
    private final QOrderRefundEntry qOrderRefundEntry;

    private final OrderMainRepository orderMainRepository;
    private final OrderLineItemRepository orderLineItemRepository;
    private final OrderAddressRepository orderAddressRepository;
    private final OrderRefundRepository orderRefundRepository;
    private final OrderTranslator orderTranslator;

    public OrderDataHandler(@Qualifier("kylinArtworkEntityManager")
                                    EntityManager entityManager,
                            OrderMainRepository orderMainRepository,
                            OrderLineItemRepository orderLineItemRepository,
                            OrderAddressRepository orderAddressRepository,
                            OrderRefundRepository orderRefundRepository,
                            OrderTranslator orderTranslator) {
       this.orderQueryFactory = new JPAQueryFactory(entityManager);
       this.qOrderMainEntry = QOrderMainEntry.orderMainEntry;
       this.qOrderLineItemEntry = QOrderLineItemEntry.orderLineItemEntry;
       this.qOrderRefundEntry = QOrderRefundEntry.orderRefundEntry;
       this.qOrderAddressEntry = QOrderAddressEntry.orderAddressEntry;

       this.orderAddressRepository = orderAddressRepository;
       this.orderMainRepository = orderMainRepository;
       this.orderLineItemRepository = orderLineItemRepository;
       this.orderRefundRepository = orderRefundRepository;

       this.orderTranslator = orderTranslator;
    }

    public OrderMainEntry saveOrderMain(OrderMainVO orderMain) {
        OrderMainEntry mainEntry = OrderMainEntry.builder()
                .userId(orderMain.getUserId())
                .orderNo(TimestampIdFactory.instance().nextId(Constants.PREFIX_ORDER_NO))
                .totalFee(orderMain.getTotalFee())
                .couponFee(orderMain.getCouponFee())
                .discountFee(orderMain.getDiscountFee())
                .freight(orderMain.getFreight())
                .payMode(orderMain.getPayMode().getCode())
                .paidFee(orderMain.getPaidFee())
                .productFee(orderMain.getProductFee())
                .state(orderMain.getState().getCode())
                .message(orderMain.getMessage())
                .payDeadline(MappingTools.toCurrentEpochSecond() + Constants.MILLI_30_MIN)
                .createdAt(MappingTools.toCurrentEpochSecond())
                .createdBy(orderMain.getCreatedBy())
                .updatedAt(Constants.LONG_MINUS_ONE)
                .updatedBy(Constants.LONG_MINUS_ONE)
                .build();
        return orderMainRepository.saveAndFlush(mainEntry);
    }

    public OrderLineItemEntry saveOrderLine(OrderLineVO lineItem) {
        OrderLineItemEntry entry = OrderLineItemEntry.builder()
                .orderId(lineItem.getOrderId())
                .commodityId(lineItem.getCommodityId())
                .campaignId(lineItem.getCampaignId())
                .boardId(lineItem.getBoardId())
                .cover(lineItem.getCover())
                .productPrice(lineItem.getProductPrice())
                .merchantId(lineItem.getMerchantId())
                .sellPrice(lineItem.getSellPrice())
                .subtitle(lineItem.getSubtitle())
                .title(lineItem.getTitle())
                .createdAt(MappingTools.toCurrentEpochSecond())
                .createdBy(lineItem.getCreatedBy())
                .updatedAt(Constants.LONG_MINUS_ONE)
                .updatedBy(Constants.LONG_MINUS_ONE)
                .build();
        return orderLineItemRepository.saveAndFlush(entry);
    }

    public OrderAddressEntry saveOrderAddress(OrderAddressVO address) {
        OrderAddressEntry addressEntry = OrderAddressEntry.builder()
                .userId(address.getUserId())
                .consignee(address.getConsignee())
                .phone(address.getPhone())
                .orderId(address.getOrderId())
                .addressId(address.getAddressId())
                .province(address.getProvince())
                .city(address.getCity())
                .county(address.getCounty())
                .address(address.getAddress())
                .postcode(address.getPostcode())
                .createdAt(MappingTools.toCurrentEpochSecond())
                .createdBy(address.getUserId())
                .updatedAt(Constants.LONG_MINUS_ONE)
                .updatedBy(Constants.LONG_MINUS_ONE)
                .build();
        return orderAddressRepository.saveAndFlush(addressEntry);
    }

    public OrderRefundEntry saveOrderRefund(OrderRefundVO refundVO) {
        OrderRefundEntry entry = OrderRefundEntry.builder()
                .orderId(refundVO.getOrderId())
                .refundNo(TimestampIdFactory.instance().nextId(Constants.PREFIX_ORDER_REFUND))
                .refundAmount(refundVO.getRefundAmount())
                .refundAt(Constants.LONG_MINUS_ONE)
                .createdAt(MappingTools.toCurrentEpochSecond())
                .createdBy(refundVO.getCreatedBy())
                .state(RefundState.REFUNDING.getCode()).build();
        return orderRefundRepository.saveAndFlush(entry);
    }

}
